<?php


namespace models\Business;


use models\Exception\Business\AlibabaproductException;
use models\Exception\Business\DeliveryException;
use models\Exception\Business\OrderException;
use models\Exception\DAO\ModelDriverException;
use models\Exception\DAO\ModelException;
use models\Exception\DAO\ModelReflectionException;
use models\Exception\DAO\ModelSqlException;
use models\Exception\Service\ServiceException;
use models\Exception\Transformer\TransformerException;
use models\Service\DeliveryService;
use models\Service\OrderService;
use Yaf\Registry;
use youliPhpLib\Common\RequestHelper;
use Yaf\Exception;

class Delivery
{
    const KUAIDI100_URL = 'http://poll.kuaidi100.com/poll/query.do';
    const KUAIDI100_CUSTOMER = '2C4DCDDCD86FCF452046E1EBD2D5601C';
    const KUAIDI100_KEY = 'RJHpQvpE7065';

    const KUAIDI100_DELIVERY_COM_ARR = [
        'STO' => 'shentong',
        'YTO' => 'yuantong',
        'ZTO' => 'zhongtong',
        'YUNDA' => 'yundakuaiyun',
        'SFEXPRESS' => 'shunfeng',
        'EMS' => 'ems',
        'BESTQJT' => 'baishiwuliu',
        'SF' => 'shunfengkuaiyun',
    ];

    /**
     * 获取物流信息列表
     * @param array $parameters
     * @return array|mixed
     * @throws DeliveryException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getDeliveryList($parameters = []) {
        try {
            return DeliveryService::getInstance()->getList(
                isset($parameters['page']) ? $parameters['page'] : 1,
                isset($parameters['page_size']) ? $parameters['page_size'] : 9999,
                isset($parameters['sort']) ? $parameters['sort'] : 'desc',
                isset($parameters['order']) ? $parameters['order'] : 'id',
                []);
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new DeliveryException(DeliveryException::DELIVERY_IS_NOT_EXISTS, DeliveryException::DELIVERY_IS_NOT_EXISTS_NO);
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 采集快递公司信息入库
     * @param array $delivery_arr
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function collectDelivery($delivery_arr = []) {
        try {
            $update_data_arr = $insert_data_arr = [];
            $delivery_id_arr  = array_column($delivery_arr, 'id');
            // 查询商品是否存在
            if (count($delivery_arr) == 1) {
                $exists['data'][] = DeliveryService::getInstance()->getOne(implode('', $delivery_id_arr));
            } else {
                $condition = ['groupOp' => 'AND', 'rules' => [
                    ['field' => 'id', 'op' => 'in', 'data' => implode(',', $delivery_id_arr)]]];
                $exists = DeliveryService::getInstance()->getList(1, count($delivery_arr), 'desc', 'id',
                    $condition);
            }

            if (!empty($exists['data'])) {
                $exists_delivery_arr = array_column($exists['data'], 'id');
                foreach ($delivery_arr as $idx => $delivery_info) {
                    // 已存在的商品写入更新数据
                    if (in_array($delivery_info['id'], $exists_delivery_arr)) {
                        array_push($update_data_arr, $delivery_info);
                    } // 不存在的商品写入插入数组
                    else {
                        array_push($insert_data_arr, $delivery_info);
                    }
                }
            } else
                $insert_data_arr = $delivery_arr;

            // 更新数组存在
            if (!empty($update_data_arr)) {
                // 更新数组长度大于1，批量插入
                if (count($update_data_arr) > 1)
                    DeliveryService::getInstance()->batchUpdate($update_data_arr);
                // 更新数组长度等于1，单条更新
                else {
                    $update_arr = array_values($update_data_arr);
                    $update_arr = $update_arr[0];
                    $delivery_id = $update_arr['id'];
                    DeliveryService::getInstance()->update($update_arr, $delivery_id);
                }
            }

            // 插入数据存在
            if (!empty($insert_data_arr))
                // 批量插入
                DeliveryService::getInstance()->batchInsert($insert_data_arr);
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    static public function getDeliveryDetailByOrderSn($parameters = []) {
        $order_info = $delivery_detail = [];
        $is_refund = isset($parameters['is_refund']) && $parameters['is_refund'] == 1;
        if (isset($parameters['from_api']) && $parameters['from_api'] === true) {
            if ($is_refund === true) {
                $order_info = RefundInfo::getRefundInfoBySn($parameters['order_sn']);
            } else {
                $order_info = OrderService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                    ['field' => 'sn', 'op' => 'eq', 'data' => $parameters['order_sn']],
                    ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                    ['field' => 'stats', 'op' => 'eq', 'data' => 2]
                ]]);
            }
        }
        if (empty($order_info))
            throw new OrderException(OrderException::ORDER_IS_NOT_EXISTS, OrderException::ORDER_IS_NOT_EXISTS_NO);

        if ($is_refund === false) {
            list($delivery_no, $delivery_no_1688, $company_name, $status) = Alibaba::getDeliveryNo($order_info['trade_order_sn']);
            if ($delivery_no_1688)
                $delivery_detail = Alibaba::getLogisticsTraceInfo($order_info['trade_order_sn'], $delivery_no_1688);

            return ['delivery_no' => $delivery_no, 'delivery_company' => $company_name, 'detail' => $delivery_detail];
        } else {
            $delivery_info = unserialize($order_info['logistics']);
            $param = [
                'com' => self::KUAIDI100_DELIVERY_COM_ARR[$delivery_info['logistics_company_no']],
                'num' => $delivery_info['freight_bill'],
                'from' => '',
                'phone' => '',
                'to' => '',
                'resultv2' => '0'
            ];
            $post_param = [
                'customer' => self::KUAIDI100_CUSTOMER,
                'param' => json_encode($param)
            ];
            $post_param['sign'] = strtoupper(md5($post_param['param'] . self::KUAIDI100_KEY . $post_param["customer"]));
            list($header_size, $resp) = RequestHelper::curlRequest(self::KUAIDI100_URL, http_build_query($post_param), 'POST');
            $resp = json_decode($resp, true);

            if ($resp['message'] != 'ok')
                throw new Exception('快递查询接口调用失败', 400);

            $content = [];
            foreach ($resp['data'] as $data) {
                array_push($content, [
                    'date' => $data['time'],
                    'content' => $data['context']
                ]);
            }

            $company_name = DeliveryService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'company_no', 'op' => 'eq', 'data' => $delivery_info['logistics_company_no']]
            ]]);

            return ['delivery_no' => $delivery_info['freight_bill'], 'delivery_company' => $company_name['company_name'], 'detail' => $content];
        }
    }

}
